/*
zoomBox.js
Brandon Kerr, Washington University in St Louis
8/14/12

Keeps track of the zoom box view for displaying a zoomed-in view
of where the user is dragging a point around on the canvas.
*/

const OFFSET_X = 20;
const OFFSET_Y = 55;

const CROSSHAIR_SIZE = 10;

const PADDING_X = 35;
const PADDING_Y = 35;

function ZoomBox() {
	this.width = 150; // size of the zoombox
	this.height = 150;

	this.scaleFactor = 2; // level of zoom

	this.containerWidth = this.getContainerWidth();
	this.containerHeight = this.getContainerHeight();

	this.leftEdge = 0;
	this.topEdge = 0;

	this.posX = 0;
	this.posY = 0;

	// offset from mouse cursor (where the box is relative to)
	this.offsetX = OFFSET_X;
	this.offsetY = OFFSET_Y;

	// flag to see if the box needs to be adjusted so the user
	// can still see it at the extremes of the window
	this.tooCloseToBottomOffset = 0;
	this.tooCloseToBottomFlag = false;

	this.active = true;
	this.zoomCanvas = document.getElementById('zoomCanvas');

	// Google earth plugin requires a "shim" or an iframe placed in front of the
	// plugin window for anything to be z-indexed on top
	this.iframeShim = document.getElementById('iframeShimZoom');
}

ZoomBox.prototype.draw = function() {
	// position the zoom box
	this.zoomCanvas.style.display = 'block';
	this.zoomCanvas.style.top = (this.posY + this.tooCloseToBottomOffset + this.offsetY - this.topEdge) + "px";
	this.zoomCanvas.style.left = (this.posX + this.offsetX - this.leftEdge) + "px";

	// if you need to display the shim, do it
	var zoomBoxEarthThreshold = this.posX + this.offsetX - this.leftEdge + this.width - 29;
	if ( zoomBoxEarthThreshold > this.containerWidth ) {
		this.iframeShim.style.top = (this.posY + this.tooCloseToBottomOffset - this.topEdge + OFFSET_Y/2 + 30) + "px";
		this.iframeShim.style.left = "0px";
		this.iframeShim.style.width = (zoomBoxEarthThreshold - this.containerWidth) + "px";
		//this.iframeShim.style.display = 'block';
	} else {
		this.iframeShim.style.display = 'none';
	}

	// erase the old zoombox
	var context = this.zoomCanvas.getContext('2d');
	context.clearRect(0, 0, this.zoomCanvas.width, this.zoomCanvas.height);
	context.fillStyle = "#CCCCCC";
	context.fillRect(0, 0, this.zoomCanvas.width, this.zoomCanvas.height);
	
	// for this next part, img is the image written to the large
	// canvas. here we determine which section of the big image
	// to take to paste into the zoom box (after zooming in)
	var sx, sy, sw, sh, dx, dy, dw, dh;
	sx = this.posX - (this.zoomCanvas.width/(2*this.scaleFactor));
	sy = this.posY - (this.zoomCanvas.height/(2*this.scaleFactor));
	sw = this.zoomCanvas.width / this.scaleFactor;
	sh = this.zoomCanvas.height / this.scaleFactor;
	dx = 0;
	dy = 0;
	dw = this.zoomCanvas.width;
	dh = this.zoomCanvas.height;

	if ( sx + sw > img.width ) {
		sw = img.width - sx;
		dw = sw * this.scaleFactor;
	} else if ( sx < 0 ) {
		sw = sw + sx;
		dx = sx * -1 * this.scaleFactor;
		dw = sw * this.scaleFactor;
		sx = 0;
	}

	if ( sy + sh > img.height ) {
		sh = img.height - sy;
		dh = sh * this.scaleFactor;
	} else if ( sy < 0 ) {
		sh = sh + sy;
		dy = sy * -1 * this.scaleFactor;
		dh = sh * this.scaleFactor;
		sy = 0;
	}

	// paste correct zoom image into the zoom canvas
	context.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);

	// draw the crosshairs in the middle
	context.moveTo(this.zoomCanvas.width/2, this.zoomCanvas.height/2 - CROSSHAIR_SIZE);
	context.lineTo(this.zoomCanvas.width/2, this.zoomCanvas.height/2 + CROSSHAIR_SIZE);
	context.stroke();
	context.moveTo(this.zoomCanvas.width/2 - CROSSHAIR_SIZE, this.zoomCanvas.height/2);
	context.lineTo(this.zoomCanvas.width/2 + CROSSHAIR_SIZE, this.zoomCanvas.height/2);
	context.stroke();
}
ZoomBox.prototype.undraw = function() {
	this.zoomCanvas.style.display = 'none';
	this.iframeShim.style.display = 'none';
}

ZoomBox.prototype.setPosition = function( x, y ) {
	this.posX = x;
	this.posY = y;

	// if the zoombox is too close to the edge of the window,
	// reverse the y component of the position
	var rect = this.zoomCanvas.getBoundingClientRect();
	if ( rect.bottom-this.tooCloseToBottomOffset > window.innerHeight+rect.height/2-10 ) this.tooCloseToBottomOffset = -rect.height;
	else this.tooCloseToBottomOffset = 0;
}

ZoomBox.prototype.changeZoomScaleFactor = function() { 
	var newFactor = document.getElementById('zoomfactorbox').value;
	this.scaleFactor = newFactor;
}

ZoomBox.prototype.updateEdges = function() {
	this.leftEdge = this.getScrollLeft();
	this.topEdge = this.getScrollTop();
}

ZoomBox.prototype.getContainerWidth = function() {
	return document.getElementById('imagecontainer').offsetWidth;
}
ZoomBox.prototype.getContainerHeight = function() {
	return document.getElementById('imagecontainer').offsetHeight;
}
ZoomBox.prototype.getScrollLeft = function() {
	return document.getElementById('imagecontainer').scrollLeft;
}
ZoomBox.prototype.getScrollTop = function() {
	return document.getElementById('imagecontainer').scrollTop;
}